#include <stdio.h>

int main()
{
    //定义一个int变量
    //变量的初始化：定义变量时给它赋值
    //变量定义一定要初始化，避免垃圾值

/*双目运算符：*/

    /*算术运算符：
        + 
        - 
        * 
        /（整除 向下取整）
        %（取余）
        +=
        -=
        *=
        /=
    */

#if 0
    int a = 10; //开辟一块空间&命名为a
    int b = 20;;
    printf("%d\n",a / b);   //整除 向下取整
#endif

#if 0
    int a = 10;
    int b = 20;
    float c = 1.0 * a / b;  //若是想要除出小数，前面需要*1.0，否则是整除向下取整
    printf("%f\n",c);
#endif

#if 0
    int a = 10;
    int b = 20;
    int c = a % b;
    printf("%d\n",c);
#endif

#if 0
    int a = 10;
    int c = 0;
    int b = 0;
    //c += a;       //c = c + a;
    //c -= a;       //c = c - a;
    b += c += a;    //多个连等表达式都是从最右边开始算
                    //b += (c = c + a)
    printf("%d\n",b);
#endif

/*单目运算符：操作数只有一个的运算符*/
    /*++ --*/
#if 0
    int a = 0;
    //int b = a++;  //给出a的值，自己+1（ps：给的是值）
    int b = ++a;  //自己+1，再给出a（ps：给的是a）
    printf("a : %d\n",a);
    printf("b : %d\n",b);
#endif

#if 0
    int a = 0;
    int b = a++ + a++;
    printf("a : %d\n",a);
    printf("b : %d\n",b);
#endif

#if 1
    int a = 0;
    int b = (++a) + (++a);
    int res = ++a;
    printf("a : %d\n",a);
    printf("b : %d\n",b);
    printf("res : %d\n", res);
#endif

/*总结：
    int a = 0;
    int b = a++ + a++;      //0 + 1 = 1
    int b = a++ + ++a;      //0 + a = 0 + 2 = 2
    int b = ++a + a++;      //a + 1 = 2 + 1 = 3
    int b = ++a + ++a;      //a + a = 2 + 2 = 4
    printf("a : %d\n",a);   //a = 2
    printf("b : %d\n",b);
*/
#if 0
    int a = 0;
    int b = a++ + ++a + a++;    //先算前两个相加，再算后面的（error：0+a+a=2a=2*3=6） 
    printf("a : %d\n",a);
    printf("b : %d\n",b);
#endif

    /*位运算符：能够操作到二进制位的运算符（C语言的底层就体现在这）*/
    
        /*
            &：按位与（可以理解为串联电路导通条件）
                0 & 1 = 0
                0 & 0 = 0   //0&任何数都是0
                1 & 1 = 1   //只有1&1才是1
                //基于这个特性可以通过按位与将某些位置0
        */
#if 0
                int c = 3;          //11
                c = c & 2;          //11 & 10
                printf("%d\n",c);   //2（可以理解为3 & 2就是取二者相同的部分）
#endif

        /*
            |：按位或
                0 | 0 = 0
                0 | 1 = 1
                1 | 1 = 1
        */
#if 0
                int c = 2;
                c = c | 1;
                printf("%d\n",c);
                //基于这个特性可以通过按位或将某些位置1
#endif

        /*
            ^：异或：相同为0 相异为1
                0 ^ 0 = 0
                1 ^ 0 = 1
                1 ^ 1 = 0
                0 ^ 1 = 1
                一个数异或0保持不变，异或1取反
        */
#if 0
                int a = 1;
                int b = 2;
                //交换它们的值
#if 0
                //借助第三个变量：
                    int temp = a;
                    a = b;
                    b = temp;
                    printf("a : %d\n",a);
                    printf("b : %d\n",b);
#endif

#if 0
                //算术法：（数形结合 数轴）
                    a = a - b;
                    b = a + b;
                    a = b - a;
                    printf("a : %d\n",a);
                    printf("b : %d\n",b);
#endif

#if 0
                //位运算：（异或）
                    a = a ^ b;  //01 ^ 10 = 11
                    b = a ^ b;  //11 ^ 10 = 01
                    a = a ^ b;  //11 ^ 01 = 10
                    //位操作直接在原数上操作，不需要引入新的变量，节省空间，其次位操作直接进行二进制计算，比算数运算的十进制计算来的快，所以位操作比普通操作速度更快，效率更高
#endif
#endif

        /* 
            ~：取反 对所有位取反，包括符号位（0取反是-1，-1取反是0）
        */
#if 0
                printf("%d\n",~0);  //0000 0000
                                    //1111 1111 取反（补码 负数）
                                    //1111 1110 反码
                                    //1000 0001 原码（-1）
                /*while(~scanf(""))
                {

                }当scanf的返回值为-1，取反后得0，也就是假的时候，会退出循环*/
#endif

        /*
            >>：右移 数据往右移 高位补0（右移一位相当于除以2,而且是整除）
            <<：左移 数据往左移 低位补0（左移一位相当于乘2）
        */
#if 0
                int a = 3;
                a = a>>1;
                printf("%d\n",a);
#endif

#if 0
                int a = 5;
                int b = 7;
                //求a+b的平均数
#if 0
                int c = (a + b) / 2;    
                printf("%d\n",c);
                //错误写法！不严谨
                //虽然两个数都在范围内，但不能保证相加之后还在范围内，会有溢出的风险
#endif

#if 0
                int c = a + (b - a) / 2;    //展开就是a/2+b/2    
                //int c = a / 2 + b / 2;    //直接写也是错的（整除）
                printf("%d\n",c);
#endif

#if 0
                //最推荐的写法
                int c = (a & b) + ((a ^ b) >> 1);   //可以理解为两个数之间相同的部分的和求平均值加上两个数之间不同的部分的和求平均值
                printf("%d\n",c);
#endif
#endif
   
    /*逻辑运算符：判断真和假（不会对原值产生任何影响，只不过对原值进行判断而已）  
        == 
        > 
        < 
        >= 
        <=
        0：假
        1：真（非0即为真）
    */
#if 0
        printf("%d\n",1 == 2);  //0：假
        printf("%d\n",1 == 1);  //1：真（非0即为真）
#endif

        /*&&：且 左右两边都成立 结果为真*/
#if 0
            int a = 5;
            //printf("%d\n",5 <= a <= 10);  //不要用这种方式表达既要又要，前面说多个连等表达式都是从最右边开始算
            printf("%d\n",a >= 5 && a <= 10);
#endif

        /*||：或 左右两边有一个成立 结果为真*/
#if 0
            printf("%d\n",a >= 5 || a <= 1);
#endif

        /*且或运算符的短路机制*/
#if 0
            int a = -1;
            int b = -1;
            (a += 1) && (a += 2);   //且的左边为假，右边不再判断
            (b += 2) || (b += 2);   //或的左边为真，右边不再判断
            printf("a : %d\n",a);
            printf("b : %d\n",b);   
#endif

        /*！：非（单目运算符） 假变真 真变假（0变1 1变0）*/
#if 0
            int a = -1;
            printf("%d\n",!a);
#endif

#if 0
/*三目运算符：(表达式) ? 为真 : 为假
            结果是一个值，不是变量本身*/

    int a = 10;
    int b = 20;
 
    printf("%d\n",a > b ? a : b);

    //把两者之间较大的值+1
    //(a > b ? a : b) += 1;   //error：表达式必须是可修改的左值（意思就是表达式左边要为变量才可以+=1）
    //所以三目运算符返回的是一个值，不是变量本身
#endif
    return 0;
}